package com.sd365.permission.centre.service.config.websocket;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Description:
 * @Author: WengYu
 * @CreateTime: 2022/06/24 20:22
 */
@Component
@ServerEndpoint("/permission/centre/v1/websocket/{id}")
@Slf4j
public class WebSocketServer {
    /**
     * 使用map保存所有连接
     */
    private static Map<String, WebSocketServer> webSocketMap = new ConcurrentHashMap<>();

    /**
     * 记录当前在线数目
     */
    private static int count = 0;

    /**
     * 当前连接（每个websocket连入都会创建一个MyWebSocket实例
     */
    private Session session;
    /**
     * 连接唯一标识也是webSocketMap的KEY
     */
    private String id;

    /**
     * 连接时出发
     * @param session
     * @param id
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("id") String id) {
        this.session = session;
        this.id = id;
        webSocketMap.put(id, this);
        addCount();
        log.info("新的连接加入：{}", this.id);
        log.info("当前连接数===========》{}", getCount());
    }

    /**
     * 接收客户端消息
     *
     * @param message
     * @param session
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        log.info("收到客户端{}消息：{}", this.id, message);
        // TODO 接受消息后续需要补充
    }

    /**
     * 指定id发送消息
     *
     * @param message
     * @param id
     * @throws IOException
     */
    public void sendMessage(String message, String id) {
        webSocketMap.forEach((k, v) -> {
            if (id.equals(k)) {
                try {
                    log.info("对id{},发送消息---》{}", id, message);
                    v.sendMessage(message);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        });
    }

    /**
     * 处理连接错误
     * @param error
     * @param session
     */
    @OnError
    public void onError(Throwable error, Session session) {
        log.info("发生错误{},{}", this.id, error.getMessage());
    }

    /**
     * 处理连接关闭
     */
    @OnClose
    public void onClose() {
        webSocketMap.remove(this.id);
        reduceCount();
        log.info("连接关闭:{}", this.id);
    }

    /**
     * 发送消息
     * @param message
     * @throws IOException
     */
    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }


    /**
     * 广播消息
     */
    public static void broadcast() {
        WebSocketServer.webSocketMap.forEach((k, v) -> {
            try {
                v.sendMessage("这是一条测试广播");
            } catch (Exception e) {
            }
        });
    }

    //获取在线连接数目
    public synchronized int getCount() {
        return count;
    }

    private synchronized void addCount() {
        WebSocketServer.count++;
    }

    private synchronized void reduceCount() {
        WebSocketServer.count--;
    }

    /**
     * 关闭客户端连接
     *
     * @param id
     * @param message
     */
    public static void close(String message, String id) {
        log.info("开始执行关闭");
        webSocketMap.forEach((k, v) -> {
            if (id.equals(k)) {
                try {
                    v.sendMessage(message);
                    v.session.close();
                    log.info("关闭{}用户成功", id);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        });
    }

}